package lol.niconico.libtest.http

import android.text.TextUtils
import android.util.Log
import okhttp3.*
import okio.Buffer
import java.io.IOException


class LogInterceptor : Interceptor {

    public var tag: String = "LogInterceptor"

    @Throws(IOException::class)
    override fun intercept(chain: Interceptor.Chain): Response {
        val request = chain.request()

        logForRequest(request)

        val response = chain.proceed(request)

        return logForResponse(response)
    }


    private fun logForResponse(response: Response): Response {
        try {
            //===>response log
            Log.e(tag, "========response'log=======")
            val builder = response.newBuilder()
            val clone = builder.build()
            Log.e(tag, "url : " + clone.request.url)
            Log.e(tag, "code : " + clone.code)
            Log.e(tag, "protocol : " + clone.protocol)
            if (!TextUtils.isEmpty(clone.message)) {
                Log.e(tag, "message : " + clone.message)
            }
            var body = clone.body
            if (body != null) {
                val mediaType = body.contentType()
                if (mediaType != null) {
                    Log.e(tag, "responseBody's contentType : $mediaType")
                    if (isText(mediaType)) {
                        val content = body.string()
                        Log.e(tag, "responseBody's content : $content")
                        body = ResponseBody.create(mediaType, content)
                        return response.newBuilder().body(body).build()
                    } else if (isPdf(mediaType) || isStream(mediaType)) {
                        return response
                    } else {
                        Log.e(tag, "mediaType not text")
                        val resp = body.string()
                        if (resp.length < 5000) {
                            Log.e(tag, "responseBody's content : $resp")
                        } else {
                            Log.e(tag, "responseBody's content : 长度超过5000")
                        }
                        body = ResponseBody.create(mediaType, resp)
                        return response.newBuilder().body(body).build()
                    }
                }
            }
            Log.e(tag, "========response'log=======end")
        } catch (e: Exception) {
            e.printStackTrace()
        }

        return response
    }

    private fun logForRequest(request: Request) {
        try {
            val url = request.url.toString()
            val headers = request.headers

            Log.e(tag, "========request'log=======")
            Log.e(tag, "method : " + request.method)
            Log.e(tag, "url : $url")
            if (headers.size > 0) {
                Log.e(tag, "headers : $headers")
            }
            val requestBody = request.body
            if (requestBody != null) {
                val mediaType = requestBody.contentType()
                if (mediaType != null) {
                    Log.e(tag, "requestBody's contentType : $mediaType")
                    if (isText(mediaType)) {
                        val bodyToString = bodyToString(request)
                        Log.e(tag, "requestBody's content : $bodyToString")
                    } else {
                        if (request.body is FormBody) {
                            Log.e(tag, "FormBody's content :")
                            val formBody = request.body as FormBody?
                            for (i in 0 until formBody!!.size) {
                                Log.e(
                                    tag,
                                    String.format(
                                        "name %s =value %s",
                                        formBody.name(i),
                                        formBody.value(i)
                                    )
                                )
                            }
                        } else {
                            Log.e(
                                tag,
                                "requestBody's content :  maybe [file part] , too large too print , ignored!"
                            )
                        }
                    }
                }
            }
            Log.e(tag, "========request'log=======end")
        } catch (e: Exception) {
            e.printStackTrace()
        }

    }

    private fun isText(mediaType: MediaType): Boolean {
        return if (mediaType.type == "text") {
            true
        } else mediaType.subtype == "json" ||
                mediaType.subtype == "xml" ||
                mediaType.subtype == "html" ||
                mediaType.subtype == "webviewhtml"
    }

    private fun isPdf(mediaType: MediaType): Boolean {
        return mediaType.type == "application" && mediaType.subtype == "pdf"
    }

    private fun isStream(mediaType: MediaType): Boolean {
        return mediaType.type == "application" && mediaType.subtype == "octet-stream"
    }

    private fun bodyToString(request: Request): String {
        return try {
            val copy = request.newBuilder().build()
            val buffer = Buffer()
            copy.body!!.writeTo(buffer)
            buffer.readUtf8()
        } catch (e: IOException) {
            "something error when show requestBody."
        }
    }
}
